package com.ktwlsoft.archivemanage.domain.business.businessService;

import com.ktwlsoft.archivemanage.domain.business.repositoryService.*;
import com.ktwlsoft.archivemanage.domain.dao.entity.*;
import com.ktwlsoft.archivemanage.payload.menu.DispatchActionRequest;
import com.ktwlsoft.archivemanage.payload.operationLog.SaveLogRequest;
import com.ktwlsoft.archivemanage.payload.security.AccountResponse;
import com.ktwlsoft.archivemanage.payload.security.ArchiveUnitResponse;
import org.apache.commons.codec.binary.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 角色安全相关
 */
@Service
public class SecurityRoleService {

    private final RoleActionRepositoryService roleActionRepositoryService;

    private final RoleMenuRepositoryService roleMenuRepositoryService;

    private final ActionSourceRepositoryService actionSourceRepositoryService;

    private final MenuSourceRepositoryService menuSourceRepositoryService;

    private final AccountRepositoryService accountRepositoryService;

    private final RoleRepositoryService roleRepositoryService;

    private final ArchiveUnitRepositoryService archiveUnitRepositoryService;

    public SecurityRoleService(RoleActionRepositoryService roleActionRepositoryService,
                               RoleMenuRepositoryService roleMenuRepositoryService,
                               ActionSourceRepositoryService actionSourceRepositoryService,
                               MenuSourceRepositoryService menuSourceRepositoryService,
                               AccountRepositoryService accountRepositoryService,
                               RoleRepositoryService roleRepositoryService,
                               ArchiveUnitRepositoryService archiveUnitRepositoryService) {
        this.roleActionRepositoryService = roleActionRepositoryService;
        this.roleMenuRepositoryService = roleMenuRepositoryService;
        this.actionSourceRepositoryService = actionSourceRepositoryService;
        this.menuSourceRepositoryService = menuSourceRepositoryService;
        this.accountRepositoryService = accountRepositoryService;
        this.roleRepositoryService = roleRepositoryService;
        this.archiveUnitRepositoryService = archiveUnitRepositoryService;
    }

    /**
     * 先删除此角色关联的所有行为和菜单，然后再添加
     *
     * @param request 分配请求
     */
    @Transactional(rollbackFor = Exception.class)
    public void dispatchActions(DispatchActionRequest request) {
        roleActionRepositoryService.deleteByRoleId(request.getRoleId());
        roleMenuRepositoryService.deleteByRoleId(request.getRoleId());
        Set<String> menuNames = new HashSet<>();
        for (DispatchActionRequest.ActionRole actionRole : request.getActionRoles()) {
            RoleMenuRelation roleMenuRelation = new RoleMenuRelation(request.getRoleId(), request.getRoleName(), actionRole.getMenuId(), actionRole.getMenuName());
            roleMenuRepositoryService.save(roleMenuRelation);

            RoleActionRelation roleActionRelation = new RoleActionRelation(request.getRoleId(), request.getRoleName(), actionRole.getActionId(), actionRole.getActionName());
            roleActionRepositoryService.save(roleActionRelation);
            //update role's rights here
            if(roleMenuRelation.getMenuName().length()>0){
                menuNames.add(roleMenuRelation.getMenuName());
//                actionNames.append(roleMenuRelation.getMenuName()+ " ");
            }
        }
//        menuNames.forEach(name -> {
//            menuNamesStr.append(name).append(" ");
//        });
        String menuNameStr = String.join(" ", menuNames);
        roleRepositoryService.updateRoleRights(request.getRoleId(), menuNameStr);
        OperationRepositoryService.saveLog(new SaveLogRequest(
                OperationLog.OperationType.AUTHORISE,
                "修改角色《"+ request.getRoleName() +"》权限",
                "角色管理",
                OperationLog.BusinessType.SYSTEM));
    }

    /**
     * 查询此角色所拥有的所有行为
     *
     * @param roleId 角色Id
     * @return 行为列表
     */
    public List<ActionSource> findActionsByRoleId(Long roleId) {
        return actionSourceRepositoryService.findByRoleId(roleId);
    }

    /**
     * 查找此用户所拥有的所有行为
     *
     * @param userName 用户
     * @return
     */
    @Transactional
    public List<ActionSource> findActionsByUserName(String userName) {
        List<Role> roles = roleRepositoryService.getByUserName(userName);
        if (hasDefaultRole(roles)) {
            return actionSourceRepositoryService.findAllAction();
        } else {
            return actionSourceRepositoryService.findActionsByUserName(userName);
        }
    }

    /**
     * 获取此用户所拥有的所有行为代码
     *
     * @param userName 用户名
     * @return 行为代码列表
     */
    @Transactional
    public List<String> findActionCodesByUserName(String userName) {
        List<Role> roles = roleRepositoryService.getByUserName(userName);
        if (hasDefaultRole(roles)) {
            return actionSourceRepositoryService.findAllActionCode();
        } else {
            return actionSourceRepositoryService.findActionCodeByUserName(userName);
        }
    }

    private boolean hasDefaultRole(List<Role> roles) {
        for (Role role :
                roles) {
            if (role.getSystemDefault()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查询所有的行为资源
     *
     * @return 行为资源列表
     */
    public List<ActionSource> findAllAction() {
        return actionSourceRepositoryService.findAllAction();
    }

    /**
     * 查询此角色所有的菜单资源
     *
     * @param roleId 角色id
     * @return 此角色所有的行为资源
     */
    public List<MenuSource> findMenusByRoleId(Long roleId) {
        return menuSourceRepositoryService.findByRoleId(roleId);
    }

    @Transactional
    public List<MenuSource> findMenusByUserName(String userName) {
        List<Role> roles = roleRepositoryService.getByUserName(userName);
        if (hasDefaultRole(roles)) {
            return menuSourceRepositoryService.findAllMenu();
        } else {
            return menuSourceRepositoryService.findByUserName(userName);
        }
    }

    /**
     * 查询所有的菜单资源
     *
     * @return 菜单资源列表
     */
    public List<MenuSource> findAllMenu() {
        return menuSourceRepositoryService.findAllMenu();
    }

    public AccountResponse findAccount(String usernameOrPhone) {
        return accountRepositoryService.findByUserName(usernameOrPhone);
    }

    public boolean existByUnitAccount(String unitAccountOrTele) {
        return archiveUnitRepositoryService.existByUnitAccountOrTele(unitAccountOrTele);
    }

    public ArchiveUnitResponse findArchiveUnitResponse(String account) {
        return archiveUnitRepositoryService.findArchiveUnitResponse(account);
    }
}
